package org.aplikator.server.descriptor;

import java.io.Serializable;

/**
 * User: vlahoda
 */
public abstract class WidgetPropertyDescriptorBase<T extends Serializable>  extends WidgetDescriptorBase implements HasProperty<T>  {

    private Property<T> property;

    protected WidgetPropertyDescriptorBase(Property<T> property) {
        this.property = property;
    }

    public Property<T> getProperty() {
        return property;
    }

    public void registerProperties(Form form) {
        form.addProperty(getProperty());
    }

    @Override
    @SuppressWarnings("unchecked")
    public Widget cloneWithReference(Reference<? extends Entity> referencingProperty){
        WidgetPropertyDescriptorBase retval;
        try {
            retval = (WidgetPropertyDescriptorBase) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new UnsupportedOperationException(e);
        }

        retval.property = getPropertyWithReference(referencingProperty);
        return retval;
    }

    @SuppressWarnings("unchecked")
    private Property<T> getPropertyWithReference(Reference<? extends Entity> referencingProperty){
        if (referencingProperty != null){
            Property rootProperty = getProperty();
            Property lastRelatedProperty = null;
            while (rootProperty.getRefferedThrough()!= null){
                lastRelatedProperty = rootProperty;
                rootProperty = rootProperty.getRefferedThrough();
            }
            Property referencedProperty =  referencingProperty.relate(rootProperty) ;
            if (lastRelatedProperty == null){
                return referencedProperty;
            } else{
                lastRelatedProperty.setRefferedThrough((Reference) referencedProperty);
                return getProperty();
            }
        }else{
            throw new IllegalArgumentException("Referencing property cannot be null -" +this);
            //return getProperty();
        }
    }

}
